package traveldream.ejb.sessionBean;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import traveldream.ejb.DTO.BookingDTO;
import traveldream.ejb.DTO.ExcursionDTO;
import traveldream.ejb.DTO.PackageDTO;
import traveldream.ejb.DTO.TransportationDTO;
import traveldream.ejb.entities.Booking;
import traveldream.ejb.entities.CustomizedPackage;
import traveldream.ejb.entities.DefaultPackage;
import traveldream.ejb.entities.Excursion;
import traveldream.ejb.entities.User;
import traveldream.ejb.entities.Hotel;
import traveldream.ejb.entities.TransportationMean;
import traveldream.ejb.interfaces.NotFindException;
import traveldream.ejb.interfaces.PackagePurchaseBeanLocal;

/**
 * Session Bean implementation class PackagePurchaseBean
 */
@Stateless
public class PackagePurchaseBean implements PackagePurchaseBeanLocal {
	
	@PersistenceContext
	private EntityManager em;
    /**
     * Default constructor. 
     */
    public PackagePurchaseBean() {
        // TODO Auto-generated constructor stub
    }

	@Override
	public void buy(PackageDTO pack) throws Exception,NotFindException{
		//DefaultPackage dP = convertFromDTO(pack);
		
		//dP.setId(pack.getId());
		try{
		DefaultPackage dP = em.find(DefaultPackage.class, pack.getId());
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
		List<User> users = dP.getBuyers();
		users.add(u);
		dP.setBuyers(users);
		em.merge(dP);
		}
		catch(NullPointerException e){
			throw new NotFindException();
		}
	}
	
	@Override
	public void booking(BookingDTO bDTO, ExcursionDTO eDTO){
		System.out.println("sono in booking");
		Booking b=new Booking();
		b.convertFromDTO(bDTO);
		em.persist(b);
		TransportationDTO gDTO=bDTO.getgDTO();
		gDTO.setAvailablePlaces(gDTO.getAvailablePlaces()-bDTO.getnOfPeople());
		TransportationMean g = new TransportationMean();
		g.convertFromDTO(gDTO);
		g.setId(gDTO.getId());
		em.merge(g);
		TransportationDTO rDTO=bDTO.getrDTO();
		rDTO.setAvailablePlaces(rDTO.getAvailablePlaces()-bDTO.getnOfPeople());
		TransportationMean r = new TransportationMean();
		r.convertFromDTO(rDTO);
		r.setId(rDTO.getId());
		em.merge(r);
		Excursion e=null;
		if(eDTO!=null){
		eDTO.setAvailablePlaces(eDTO.getAvailablePlaces()-bDTO.getnOfPeople());
		e = new Excursion(eDTO);
		e.setId(eDTO.getId());
		em.merge(e);
		}
		Hotel h=new Hotel(bDTO.gethDTO());
		h.setId(bDTO.gethDTO().getId());
		checkPackagesAvailability(g,r,e,h);
	}
	
	private void checkPackagesAvailability(TransportationMean g, TransportationMean r, Excursion e,Hotel h){
		List<DefaultPackage> dP=new ArrayList<DefaultPackage>();
		Query query;
		if(g.getAvailable_Places()<1){
			query=em.createNamedQuery("DefaultPackage.findByG");
			query.setParameter("g",g);
			dP=query.getResultList();
			for(int i=0;i<dP.size();i++){
				System.out.println("Sto settando invalid "+dP.get(i).getId());
				dP.get(i).setInvalid(true);
				em.merge(dP.get(i));
			}
		}
			if(r.getAvailable_Places()<1){
				query=em.createNamedQuery("DefaultPackage.findByR");
				query.setParameter("r",r);
				dP=query.getResultList();
				for(int i=0;i<dP.size();i++){
					System.out.println("Sto settando invalid "+dP.get(i).getId());
					dP.get(i).setInvalid(true);
					em.merge(dP.get(i));
				}
			}
			if(e!=null)
				if(e.getAvailable_Places()<1){
					query=em.createNamedQuery("DefaultPackage.findByE");
					query.setParameter("e",e);
					dP=query.getResultList();
					for(int i=0;i<dP.size();i++){
						dP.get(i).setInvalid(true);
						em.merge(dP.get(i));
					}
				}
				query=em.createNamedQuery("Booking.findAvl");
				query.setParameter("h",h);
				query.setParameter("arr_date",r.getDeparture_Date());
				query.setParameter("dep_date",g.getArrival_Date());
				if(h.getAvailable_Places()<=(Long)query.getSingleResult()){
					query=em.createNamedQuery("DefaultPackage.findByH");
					query.setParameter("h",h);
					dP=query.getResultList();
					for(int i=0;i<dP.size();i++){
						dP.get(i).setInvalid(true);
						System.out.println("Ho settato invalid "+dP.toString());
						em.merge(dP.get(i));
						System.out.println("Ho fatto Merge"+dP.toString());
					}
				}
	}
	
	public DefaultPackage convertFromDTO(PackageDTO pDTO){
    	DefaultPackage dP = new DefaultPackage();
    	dP.setName(pDTO.getName());
    	dP.setNation(pDTO.getNation());
    	dP.setPrice(pDTO.getPrice());
    	dP.setDescription(pDTO.getDescription());
    	dP.setHotel(em.find(Hotel.class, pDTO.getIdHotel()));
    	dP.setExcursion(em.find(Excursion.class, pDTO.getIdExcursion()));
    	dP.setTransport_arr(em.find(TransportationMean.class, pDTO.getIdReturn()));
    	dP.setTransport_dep(em.find(TransportationMean.class, pDTO.getIdGoing()));
    	dP.setInvalid(false);
    	return dP;
    }
	
	public CustomizedPackage convertFromCDTO(PackageDTO pDTO){
    	CustomizedPackage cP = new CustomizedPackage();
    	cP.setName(pDTO.getName());
    	cP.setNation(pDTO.getNation());
    	cP.setPrice(pDTO.getPrice());
    	cP.setDescription(pDTO.getDescription());
    	cP.setHotel(em.find(Hotel.class, pDTO.getIdHotel()));
    	cP.setExcursion(em.find(Excursion.class, pDTO.getIdExcursion()));
    	cP.setArrival_Transport(em.find(TransportationMean.class, pDTO.getIdReturn()));
    	cP.setDeparture_Transport(em.find(TransportationMean.class, pDTO.getIdGoing()));
    	cP.setInvalid(false);
    	return cP;
    }
    

	@Override
	public void buyCustomize(PackageDTO pack) {
		CustomizedPackage cP = convertFromCDTO(pack);
		FacesContext context = FacesContext.getCurrentInstance();
        ExternalContext externalContext = context.getExternalContext();
        String user = externalContext.getUserPrincipal().getName();
        User u = em.find(User.class, user);
        cP.setEmail_Customer(u);
        em.persist(cP);
		
	}

	@Override
	public boolean checkAvailability(BookingDTO bDTO, ExcursionDTO eDTO) {
		// TODO Auto-generated method stub
		if(bDTO.getgDTO().getAvailablePlaces()<bDTO.getnOfPeople())
			return false;
		if(bDTO.getrDTO().getAvailablePlaces()<bDTO.getnOfPeople())
			return false;
		if(eDTO!=null)
			if(eDTO.getAvailablePlaces()<bDTO.getnOfPeople())
				return false;
		Query query=em.createNamedQuery("Booking.findAvl",Booking.class);
		Hotel h=new Hotel(bDTO.gethDTO());
		h.setId(bDTO.gethDTO().getId());
		query.setParameter("h",h);
		query.setParameter("arr_date",bDTO.getrDTO().getDepartureDate());
		query.setParameter("dep_date",bDTO.getgDTO().getArrivalDate());
		try{
		if(bDTO.gethDTO().getAvailablePlaces()-bDTO.getnOfPeople()<(Long) query.getSingleResult())
			return false;
		}
		catch(NullPointerException e){
			System.out.println("no hotel booking");
		}
		return true;
	}

}
